﻿using System;
using System.Collections.Generic;
using System.Configuration;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Net;
using System.Reflection;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using System.Web;

namespace Ymatou.ServiceCenter
{
    internal static class Utils
    {
        /// <summary>
        /// 检测IP地址规则的正则表达式
        /// </summary>
        private const string Pattern =
            @"^(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])$";

        private static string _localIp = null;

        private static string _assemblyVersion = null;
        private static string GetLocalIp() //获取本地IP 
        {
            try
            {
                if (_localIp != null) return _localIp;
                IPAddress[] ipAddrs = Dns.GetHostAddresses(Dns.GetHostName());
                string ip = string.Empty;
                foreach (IPAddress ipAddr in ipAddrs)
                {
                    ip = ipAddr.ToString();
                    if (IsIp(ip))
                        break;
                }
                _localIp = ip;
                return _localIp;
            }
            catch
            {
                return null;
            }
        }

        public static string GetAssemblyVersion()
        {
             if (!string.IsNullOrWhiteSpace(_assemblyVersion))
                 return _assemblyVersion;
            _assemblyVersion = typeof (Utils).Assembly.GetName().Version.ToString();
            return _assemblyVersion;
        }
        /// <summary>
        /// IP地址验证的正则表达式
        /// </summary>
        private static readonly Regex PatternRegex = new Regex(Pattern);

        public static bool IsIp(string ip)
        {
            return !string.IsNullOrWhiteSpace(ip) && PatternRegex.IsMatch(ip.Trim());
        }

        /// <summary>
        /// 本机IP
        /// </summary>
        public static string LocalIp
        {
            get { return _localIp ?? (_localIp = GetLocalIp()); }
        }

        public static TAttribute GetFirstAttribute<TAttribute>(Type type, bool inherit)
        {
            var attrs = type.GetCustomAttributes(typeof (TAttribute), inherit);
            return (TAttribute) (attrs.Length > 0 ? attrs[0] : null);
        }

        public static IList<TAttribute> GetAttributes<TAttribute>(Assembly assembly, bool inherit)
        {
            if (assembly == null)
                return null;
            IList<TAttribute> list = new List<TAttribute>();
            var attrs = assembly.GetCustomAttributes(typeof (TAttribute), inherit);
            if (attrs == null || attrs.Length <= 0)
                return list;
            for (int i = 0; i < attrs.Length; i++)
            {
                if (attrs[i] == null)
                    continue;
                list.Add((TAttribute) attrs[i]);
            }
            return list;
        }

        public static IList<TAttribute> GetAttributes<TAttribute>(Type type, bool inherit)
        {
            if (type == null)
                return null;
            IList<TAttribute> list = new List<TAttribute>();
            var attrs = type.GetCustomAttributes(typeof (TAttribute), inherit);
            if (attrs.Length <= 0)
                return list;
            for (int i = 0; i < attrs.Length; i++)
            {
                if (attrs[i] == null)
                    continue;
                list.Add((TAttribute) attrs[i]);
            }
            return list;
        }

        public static IList<TAttribute> GetAttributes<TAttribute>(MethodInfo methodInfo, bool inherit)
        {
            if (methodInfo == null)
                return null;
            IList<TAttribute> list = new List<TAttribute>();
            var attrs = methodInfo.GetCustomAttributes(typeof (TAttribute), inherit);
            if (attrs.Length <= 0)
                return list;
            for (int i = 0; i < attrs.Length; i++)
            {
                if (attrs[i] == null)
                    continue;
                list.Add((TAttribute) attrs[i]);
            }
            return list;
        }

        public static TAttribute GetFirstAttribute<TAttribute>(PropertyInfo propertyInfo, bool inherit)
        {
            var attrs = propertyInfo.GetCustomAttributes(typeof (TAttribute), inherit);
            return (TAttribute) (attrs.Length > 0 ? attrs[0] : null);
        }

        public static string GetFullTypeName(this Type type)
        {
            if (type == null)
                return string.Empty;
            return string.Concat(type.ToString(), ",", type.Assembly.FullName.Split(',')[0]);
        }

        public static string GetServiceCenterHost()
        {
            string host = ConfigurationManager.AppSettings["ServiceCenterHost"];
            if (string.IsNullOrWhiteSpace(host))
                return "http://rpc.iapi.ymatou.com";
            return host;
        }

        public static string ServiceMetadataLocalConfigPath(string appId)
        {
            if (string.IsNullOrWhiteSpace(appId))
                throw new ArgumentNullException("appId");
            string localConfigDirectory = ConfigurationManager.AppSettings["ServiceCenter.LocalConfigDirectory"];
            if (string.IsNullOrWhiteSpace(localConfigDirectory))
            {
                localConfigDirectory = "D:\\ServiceCenterConfig\\ServiceMetadata";
            }
            return Path.Combine(localConfigDirectory,Utils.GetConsumerAppId(), string.Format("{0}.config", appId));
        }

        public static string ServiceConfigLocalConfigPath(string appId)
        {
            if (string.IsNullOrWhiteSpace(appId))
                throw new ArgumentNullException("appId");
            string localConfigDirectory = ConfigurationManager.AppSettings["ServiceCenter.LocalConfigDirectory"];
            if (string.IsNullOrWhiteSpace(localConfigDirectory))
            {
                localConfigDirectory = "D:\\ServiceCenterConfig\\ServiceConfig";
            }
            return Path.Combine(localConfigDirectory, Utils.GetConsumerAppId(), string.Format("{0}.config", appId));
        }

        public static string GetConsumerAppId()
        {
            string consumerAppId = ConfigurationManager.AppSettings["AppId"];
            if (string.IsNullOrWhiteSpace(consumerAppId))
                throw new ArgumentNullException("AppId");
            return consumerAppId;
        }

        public static bool GetEnableWriteRpcDebugLog()
        {
            try
            {
                string str = ConfigurationManager.AppSettings["EnableWriteRpcDebugLog"];
                if (string.IsNullOrWhiteSpace(str))
                    return true;
                bool flag = true;
                bool.TryParse(str.Trim(), out flag);
                return flag;
            }
            catch
            {
                return true;
            }
        }

        /// <summary>
        /// 获取web客户端ip
        /// </summary>
        /// <returns></returns>
        public static string GetWebClientIp(HttpRequest httpRequest)
        {
            try
            {
                if (httpRequest == null)
                    return LocalIp;
                string clientIp = httpRequest.Headers.Get("ClientIp");
                if (!string.IsNullOrWhiteSpace(clientIp))
                    return clientIp;
                clientIp = GetClientIp(httpRequest);
                if (clientIp.Contains(":"))
                {
                    clientIp = clientIp.Replace("::ffff:", "");
                }
                if (!clientIp.Contains(",")) return clientIp;
                string[] arrs = clientIp.Split(',');
                if (arrs.Length > 0)
                {
                    clientIp = arrs[0];
                }
                return clientIp;
            }
            catch
            {
                return null;
            }
        }

        private static string GetClientIp(HttpRequest httpRequest)
        {
            try
            {
                //如果不是http服务程序，则获取本机IP
                if (httpRequest==null)
                {
                    return LocalIp;
                }
             
                // get forward list (from proxy)
                string forwardStr = httpRequest.ServerVariables["HTTP_X_FORWARDED_FOR"];
                if (!string.IsNullOrEmpty(forwardStr))
                {
                    // from proxy
                    string[] forwardList = forwardStr.Split(',');
                    if (forwardList.Length >= 1)
                    {
                        var ip = forwardList[0].Trim();
                        //if (ip.StartsWith("10.") 
                        //    || ip.StartsWith("172.")
                        //    || ip.StartsWith("127.")
                        //    || ip.StartsWith("192.168."))
                        //{
                        //    //ApplicationLog.Debug("*****GetClientIp HTTP_X_FORWARDED_FOR: " + forwardStr);
                        //}
                      return ip;
                    }

                    if (!forwardStr.StartsWith("10."))
                    {
                        return forwardStr;
                    }
                }
                
                // get cdn ip if exists
                string clientIp = httpRequest.ServerVariables["HTTP_Cdn_Src_Ip"];
                if (!string.IsNullOrEmpty(clientIp))
                {
                    //ApplicationLog.Debug("*****GetClientIp HTTP_Cdn_Src_Ip: " + clientIp);
                    return clientIp;
                }

                // get default ip
                clientIp = httpRequest.ServerVariables["REMOTE_ADDR"];
                //ApplicationLog.Debug("*****GetClientIp REMOTE_ADDR: " + clientIp);
                // return default ip
                return clientIp;
            }
            catch (Exception ex)
            {
                return null;
            }
        }

        public static string GetServerIpLink(HttpRequest httpRequest)
        {
            try
            {
                string serverIpLink = httpRequest.Headers.Get("ServerIpLink");
                serverIpLink = string.IsNullOrWhiteSpace(serverIpLink)
                    ? Utils.LocalIp
                    : string.Concat(serverIpLink, ",", Utils.LocalIp);
                return serverIpLink;
            }
            catch
            {
                return null;
            }
        }
    }
}
